import { reactive, render, h, onMounted } from 'vue'
import Card from './Card.vue'
import { useRequest } from 'alova'
import { feedListGetter } from '@/service/methods/feed'
import type { ItemOption } from './types'
import { useRoute, useRouter } from 'vue-router'
import Routes from '@/router/routes'

// 计算真实高度，这里只计算除了图片的高度
function getRealHeight(item: ItemOption, realWidth: number) {
  const dom = document.createElement('div')

  render(
    h(Card, {
      item: item,
      width: realWidth + 'px',
      noImage: true
    }),
    dom
  )

  document.body.appendChild(dom)

  // 获取高度
  const height: number = dom.firstElementChild?.clientHeight || 100

  // 移除新容器
  document.body.removeChild(dom)
  // 返回高度
  return height
}

const useWaterfall = () => {
  const router = useRouter()
  const route = useRoute()
  const backTop = () => {
    window.scrollTo({
      top: 0,
      behavior: 'instant'
    })
  }

  // 瀑布流的一些属性
  const waterfallOption = reactive({
    /** 加载中 */
    loading: false,
    /** 距离底部多少加载更多 */
    bottomDistance: 800,
    // 是否只展示图片，这是自定义加的一个属性
    onlyImage: false,
    /** 顶部预加载屏数量 */
    topPreloadScreenCount: 0,
    /** 底部预加载屏数量 */
    bottomPreloadScreenCount: 0,
    /** 是否开启虚拟列表 */
    virtual: true,
    /** 间隔 */
    gap: 15,
    /** 每个元素最小宽度 */
    itemMinWidth: 220,
    /** 最小列数 */
    minColumnCount: 2,
    /** 最大列数 */
    maxColumnCount: 10
  })

  // 瀑布流元素高度的计算函数
  const calcItemHeight = (item: ItemOption, itemWidth: number) => {
    let height = 0
    // 当包含图文时，需要单独计算文字部分的高度
    // 文字部分的高度 + 图片的高度 = 真实高度
    if (!waterfallOption.onlyImage) {
      height = getRealHeight(item, itemWidth)
    }
    return item.height * (itemWidth / item.width) + height
  }

  // 需要展示数据的属性
  const data = reactive({
    page: 1,
    size: 30,
    total: 0,
    /** 总页数 */
    max: 0,
    list: [] as ItemOption[],
    end: false
  })

  const { send: loadFeedList, loading } = useRequest(
    () => feedListGetter({ page_num: data.page, page_size: data.size, show_nsfw: true }),
    { immediate: false }
  )
  // 加载更多数据的函数
  const loadData = async () => {
    if (data.end) {
      return
    }
    waterfallOption.loading = true
    const result = await loadFeedList()
    waterfallOption.loading = false
    data.page++
    data.total = result.total
    data.list = [...data.list, ...result.data]
  }
  // 检查是否加载更多
  const checkScrollPosition = async () => {
    if (route.name !== Routes.home) return
    if (loading.value) {
      return
    }

    const scrollHeight = document.documentElement.scrollHeight
    const scrollTop = document.documentElement.scrollTop
    const clientHeight = document.documentElement.clientHeight

    const distanceFromBottom = scrollHeight - scrollTop - clientHeight

    // 不大于最小底部距离就加载更多
    if (distanceFromBottom <= waterfallOption.bottomDistance) {
      await loadData()
    }

    // requestAnimationFrame(checkScrollPosition)
  }

  const handleCardOpen = (feed: ItemOption) => {
    const state = JSON.stringify(feed)
    router.push({ name: Routes.feedDetail, state: { feed: state } })
  }

  onMounted(() => {
    loadData()
    window.addEventListener('scroll', checkScrollPosition)
  })
  onUnmounted(() => {
    window.removeEventListener('scroll', checkScrollPosition)
  })

  return {
    backTop,
    waterfallOption,
    data,
    calcItemHeight,
    handleCardOpen
  }
}

export default useWaterfall
